<template>
  <div>
    <!-- 人才流动分析 -->
    <div id="chartOne"></div>
  </div>
</template>

<script>
export default {
  props: {
    data: {
      type: Array,
    },
  },
  data() {
    return {
      companyName: this.$cookie.get("companyName") || "",
      chartData: {
        nodes: [],
        edges: [],
      },
      scrollWidth: 0,
      scrollHeight: 0,
      rootNodeWidth: 109,
      rootNodeHeight: 109,
      colors: ["#425fd7", "#31b6a5", "#ef984b"],
    };
  },
  methods: {
    init() {
      this.scrollWidth = document.getElementById("chartOne").scrollWidth;
      this.scrollHeight = document.getElementById("chartOne").scrollHeight;
      this.initrG6();
    },
    // 自定义节点
    initrG6() {
      // 中心节点
      G6.registerNode(
        "rootNode",
        {
          draw(cfg, group) {
            const width = 109;
            const height = 109;
            const mWidth = 55;
            const mHeight = 55;
            const style = cfg.style;

            const keyShape = group.addShape("circle", {
              attrs: {
                ...style,
                x: width / 2,
                y: height / 2,
                r: width / 2,
              },
              name: "rootKeyShape",
              draggable: true,
            });

            const circleImg1 = group.addShape("image", {
              attrs: {
                width,
                height,
                img:
                  "",
              },
              name: "circleImg1",
              draggable: true,
            });

            const circleImg2 = group.addShape("image", {
              attrs: {
                width: mWidth,
                height: mHeight,
                x: (width - mWidth) / 2,
                y: (height - mHeight) / 2,
                img:
                  "",
              },
              name: "circleImg2",
              draggable: true,
            });

            const content =
              cfg.label && cfg.label.length > 12
                ? cfg.label.substr(0, 10) + "..."
                : cfg.label;
            const text = group.addShape("text", {
              attrs: {
                textAlign: "center",
                textBaseline: "top",
                text: content,
                x: width / 2,
                y: height + 10,
                fill: "#31b6a5",
                fontSize: 20,
                fontWeight: "bold",
                textAlign: "center",
                lineHeight: 20,
              },
              name: "rootTextShape",
              draggable: true,
            });

            return keyShape;
          },
        },
        "circle"
      );

      // 子节点
      G6.registerNode(
        "childNode",
        {
          draw(cfg, group) {
            const width = 55;
            const height = 55;
            const style = cfg.style;

            const keyShape = group.addShape("circle", {
              attrs: {
                ...style,
                x: width / 2,
                y: height / 2,
                // r: width / 2
              },
              name: "childNodeKeyShape",
              draggable: true,
            });

            // 如果是高危则在外层添加红色圆框
            if (cfg.highRisk) {
              group.addShape("circle", {
                attrs: {
                  x: width / 2,
                  y: height / 2,
                  r: 70 / 2,
                  lineWidth: 2,
                  stroke: "red",
                },
                name: "childNodeCircle1",
                draggable: true,
              });
            }

            // 背景色
            let bgColor =
              cfg.dataType === 0
                ? "#425fd7"
                : cfg.dataType === 1
                ? "#31b6a5"
                : "#ef984b";

            group.addShape("circle", {
              attrs: {
                x: width / 2,
                y: height / 2,
                r: width / 2,
                lineWidth: 2,
                fill: bgColor,
              },
              name: "childNodeCircle2",
              draggable: true,
            });

            // 公司图标
            group.addShape("image", {
              attrs: {
                width,
                height,
                img:
                  "",
              },
              name: "circleImg1",
              draggable: true,
            });

            let content =
              cfg.label && cfg.label.length > 12
                ? cfg.label.substr(0, 10) + "..."
                : cfg.label;
            let text1Y = height + (cfg.highRisk ? 14 : 10);
           group.addShape("text", {
              attrs: {
                textAlign: "center",
                textBaseline: "top",
                text: content,
                x: width / 2,
                y: text1Y,
                fill: "#373275",
                fontSize: 14,
                textAlign: "center",
                lineHeight: 16,
              },
              name: "childNodeTextShape1",
              draggable: true,
            });

            if (cfg.highRisk) {
              group.addShape("text", {
                attrs: {
                  textAlign: "center",
                  textBaseline: "top",
                  text: "(高危企业)",
                  x: width / 2,
                  y: text1Y + 18,
                  fill: "#d96f6f",
                  fontSize: 14,
                  textAlign: "center",
                  lineHeight: 16,
                },
                name: "childNodeTextShape2",
                draggable: true,
              });
            }
            return keyShape;
          },
        },
        "circle"
      );

      // 连线
      G6.registerEdge(
        "flowLine",
        {
          afterDraw(cfg, group) {
            // 获取图形组中的第一个图形，在这里就是边的路径图形
            const shape = group.get("children")[0];

            // 获取路径图形的中点坐标
            const midPoint = shape.getPoint(0.5);

            const { startPoint, endPoint } = cfg;

            // 箭头长度、高度
            const arrowWidth = 14;
            const arrowHeight = 14;

            // 计算箭头偏移距离
            let d =
              Math.sqrt(
                Math.pow(startPoint.x - endPoint.x, 2) +
                  Math.pow(startPoint.y - endPoint.y, 2)
              ) || 0;

            // 颜色
            let color =
              cfg.dataType === 0
                ? "#425fd7"
                : cfg.dataType === 1
                ? "#31b6a5"
                : "#ef984b";

            if (cfg.dataType === 0) {
              // 引入
              group.addShape("path", {
                attrs: {
                  path: [
                    ["M", startPoint.x, startPoint.y],
                    ["L", endPoint.x, endPoint.y],
                  ],
                  endArrow: {
                    path: G6.Arrow.vee(arrowWidth, arrowHeight, d / 4 - 7),
                    fill: color,
                  },
                },
                name: "path-shape",
              });
            } else if (cfg.dataType === 1) {
              // 跳槽
              group.addShape("path", {
                attrs: {
                  path: [
                    ["M", startPoint.x, startPoint.y],
                    ["L", endPoint.x, endPoint.y],
                  ],
                  startArrow: {
                    path: G6.Arrow.vee(arrowWidth, arrowHeight, d / 4 - 7),
                    fill: color,
                  },
                },
                name: "path-shape",
              });
            } else if (cfg.dataType === 2) {
              // 既有引入 又有跳槽
              group.addShape("path", {
                attrs: {
                  path: [
                    ["M", startPoint.x, startPoint.y],
                    ["L", endPoint.x, endPoint.y],
                  ],
                  startArrow: {
                    path: G6.Arrow.vee(
                      arrowWidth,
                      arrowHeight,
                      d / 4 - arrowHeight / 2
                    ),
                    fill: color,
                  },
                  endArrow: {
                    path: G6.Arrow.vee(
                      arrowWidth,
                      arrowHeight,
                      d / 4 - arrowHeight / 2
                    ),
                    fill: color,
                  },
                },
                name: "path-shape",
              });
            }
          },
          // 响应状态变化
          setState(name, value, item) {
            const group = item.getContainer();
            const shape = group.get("children")[0]; // 顺序根据 draw 时确定

            if (name === "color0") {
              // 引入
              if (value) {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#425fd7",
                });
              } else {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#c8c4e6",
                });
              }
            }
            if (name === "color1") {
              // 跳槽
              if (value) {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#31b6a5",
                });
              } else {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#c8c4e6",
                });
              }
            }
            if (name === "color2") {
              // 既有引入 又有跳槽
              if (value) {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#ef984b",
                });
              } else {
                shape.attr({
                  lineWidth: 3,
                  stroke: "#c8c4e6",
                });
              }
            }
          },
          // update这里的设置非常重要，必须要写
          update: undefined,
        },
        "line"
      );
    },
    // 获取数据
    getChartData() {
      let sourceData = JSON.parse(JSON.stringify(this.data));
      let companyArr = [];

      sourceData.forEach((v) => {
        if (v.info) {
          companyArr.push(v.info.an);
        }
      });
      companyArr = Array.from(new Set(companyArr));

      let companyData = [];
      companyArr.forEach((v) => {
        let obj = {
          company: v,
          output: [],
          input: [],
        };
        sourceData.forEach((b) => {
          if (b.info && b.info.an === v) {
            if (b.state.indexOf("离职") > -1) {
              obj.output.push({
                name: b.name,
                child: b.child || [],
              });
            } else {
              obj.input.push({
                name: b.name,
                child: b.child || [],
              });
            }
          }
        });
        companyData.push(obj);
      });

      // 根节点
      let rootNode = {
        id: this.companyName,
        label: this.companyName,
        type: "rootNode",
        x: (this.scrollWidth - this.rootNodeWidth) / 2,
        y: (this.scrollHeight - this.rootNodeHeight) / 2,
      };

      let chartData = {
        nodes: [rootNode],
        edges: [],
      };

      companyData.forEach((v) => {
        let dataType = 0; // 判断 离职、引入、既有离职又有引入
        let label = []; // 展示信息
        if (v.input.length > 0 && v.output.length > 0) {
          dataType = 2;
          label = [`跳槽${v.output.length}人`, `引入${v.input.length}人`];
        } else if (v.output.length > 0) {
          dataType = 1;
          label = [`跳槽${v.output.length}人`];
        } else {
          dataType = 0;
          label = [`引入${v.input.length}人`];
        }
        // 节点
        chartData.nodes.push({
          id: v.company,
          label: v.company,
          type: "childNode",
          dataType,
        });
        // 连线
        chartData.edges.push({
          source: v.company,
          target: this.companyName,
          dataType,
          output: v.output,
          input: v.input,
          label,
          labelCfg: {
            refX: -10,
            refY: 26,
            style: {
              fill: this.colors[dataType],
            },
          },
        });
      });

      chartData.nodes.sort((a, b) => {
        return b.dataType - a.dataType;
      });

      this.renderChart(chartData);
    },
    renderChart(chartData) {
      let graph = new G6.Graph({
        container: "chartOne",
        width: this.scrollWidth,
        height: this.scrollHeight,
        layout: {
          type: "force",
          center: [this.scrollWidth / 2, this.scrollHeight / 2 - 60],
          linkDistance: (param) => {
            let x = param.source.x;
            let y = param.source.x;
            let distance = 250;
            if (x <= this.scrollWidth / 3 || x >= this.scrollWidth * (3 / 4)) {
              distance = 450;
            }
            return distance;
          },
          nodeSize: [109, 109],
          preventOverlap: true,
          // clustering: true,
          // type: 'fruchterman',
          // gravity: 10,
          // speed: 10,
          // clustering: true,
          // clusterGravity: 50,
          // gravity: 1,              // 可选
          // speed: 5,                 // 可选
          // clustering: false,         // 可选
          // clusterGravity: 10,       // 可选
          // maxIteration: 2000,       // 可选，迭代次数
          // workerEnabled: true       // 可选，开启 web-worker  }
        },
        modes: {
          default: [
            "drag-canvas",
            "drag-node",
            "zoom-canvas",
            {
              type: "tooltip",
              formatText: (model) => {
                let str = `<div class="tip-box">${model.label}</div>`;
                return str;
              },
            },
            {
              type: "edge-tooltip",
              formatText: (model) => {
                let str = `
                  <h4>业务影响</h4>
                  <div class="tip-box">
                  `;
                let ouputStr = "";
                let inputStr = "";
                if (model.output.length > 0) {
                  let people = []; // 人才
                  let field = []; // 领域
                  model.output.forEach((v) => {
                    people.push(v.name);
                    if (v.child.length > 0) {
                      v.child.forEach((b) => {
                        field.push(b.key);
                      });
                    }
                  });
                  field = Array.from(new Set(field));
                  ouputStr = `
                    <p>${people.join("、")}</p>
                    <p><span class="bold">${model.output.length}人</span>跳槽${
                    model.source
                  }</p>
                  `;
                  if (field.length > 0) {
                    ouputStr += `<p><span class="bold">${field.join(
                      "、"
                    )}</span>可能存在业务影响</p>`;
                  }

                  str += ouputStr;
                }

                if (model.input.length > 0) {
                  let people = []; // 人才
                  let field = []; // 领域
                  model.input.forEach((v) => {
                    people.push(v.name);
                    if (v.child.length > 0) {
                      v.child.forEach((b) => {
                        field.push(b.key);
                      });
                    }
                  });
                  field = Array.from(new Set(field));
                  inputStr = `
                    <p>${people.join("、")}</p>
                    <p><span class="bold">${model.input.length}人</span>从${
                    model.source
                  }引入</p>
                  `;

                  if (field.length > 0) {
                    inputStr += `<p><span class="bold">${field.join(
                      "、"
                    )}</span>可能存在业务影响</p>`;
                  }

                  str += inputStr;
                }

                str += "</div>";

                return str;
              },
            },
          ],
        },
        defaultNode: {
          type: "rootNode",
        },
        defaultEdge: {
          type: "flowLine",
          style: {
            lineWidth: 2,
            lineAppendWidth: 3,
            stroke: "#c8c4e6",
            lineDash: [3],
          },
          labelCfg: {
            autoRotate: false,
            style: {
              fontWeight: "normal",
              fontSize: 12,
            },
          },
        },
        animate: true,
      });

      // let newNodes = []
      // chartData.nodes.forEach(v => {
      //   if (v.type !== 'rootNode') {
      //     newNodes.push(v)
      //   }
      // })
      // let newEdges = chartData.edges
      // const subForceLayout = new G6.Layout.force({
      //   center: [chartData.nodes[0].x + this.rootNodeWidth / 2, chartData.nodes[0].y + 40],
      //   preventOverlap: true,
      //   nodeSize: [109, 109],
      //   linkDistance: (param) => {
      //     let x = param.target.x
      //     let y = param.target.y
      //     let distance = 100
      //     // if (x <= this.scrollWidth / 3 || x >= this.scrollWidth * (2/3)) {
      //     //   distance = this.scrollHeight / 3 + 50
      //     // }
      //     return distance
      //   },
      //   // nodeSize: [109, 60],
      //   tick: function tick() {
      //     // the tick function to show the animation of layout process
      //     graph.refreshPositions()
      //   },
      // });
      // subForceLayout.init({
      //   nodes: newNodes,
      //   edges: newEdges
      // });
      // subForceLayout.execute()

      graph.read(chartData);

      graph.on("edge:mouseenter", (ev) => {
        const edge = ev.item;
        const model = edge.getModel();
        let name = "color" + model.dataType;
        graph.setItemState(edge, name, true);
      });

      graph.on("edge:mouseleave", (ev) => {
        const edge = ev.item;
        const model = edge.getModel();
        let name = "color" + model.dataType;
        graph.setItemState(edge, name, false);
      });
    },
  },
  watch: {
    data() {
      this.getChartData();
    },
  },
  mounted() {
    this.init();
    if (this.data.length > 0) {
      this.getChartData();
    }
  },
  beforeDestroy() {},
};
</script>

<style lang="scss" scoped>
#chartOne {
  width: 100%;
  height: 630px;
}
</style>
